﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace DbViewDriver
{
	// interface to an object that wraps a data source (typically a database)
	//
	public interface IDataSource : IDisposable
	{
		// 3rd party database drivers may need to be installed on the host machine
		// before they will work. eg SQL Server CE of SQLLite. This call will check
		// the installation and return  meaningful help if there is a problem
		bool PerformDriverCheck(out String configErrorMessage);
		
		// Property to use in selection lists
		String DriverName { get; }

		// Database connection string property  
		String ConnectionString{get;}
		// Set connection from configuration
		void  SetCurrentConnection(DbView.ConnectionInfo connectionInfo);

		// Configure driver. Return T if the current connection was reset
		bool ConfigureConnection(IConnectionConfig connectionConfig);

		// Supports the given command
		bool SupportsCommand(DbView.Commands.Cmnd command);

		// Is this a Developer database in which case switch on dangerous stuff
		bool IsDevelopmentDatabase {get; }

		// populate the datatable from a command string
		DataTable BuildTable(DbView.Command command, DbView.ViewContext context);
		// Return the source for objects in a single string
		String GetSourceCode(DbView.Command command);
		// preferred version. Will hopfully remove the other 
		String GetSourceCode(DbView.ViewContext context, String objectName);
		// Do some action. Return a command if necessary
		// return options:
		// if Command = Nothing 
		//    if refreshGrid = false then no further action
		//    if refreshGrid = true then refresh grid (ie. there is a change in the grid to update)
		// If Command != Nothing executes the return command with an empty filter string
		DbView.Command ExecuteDriverAction(DbView.Command command, object window, 
											DbViewDriver.IConnectionConfig connections, 
											String searchText, out bool refreshGrid);
		
		// Update data in the table. Return t/f success fail with details in statusMessage
		bool Update(DataTable table, out String statusMessage);

		// populate the datatable from a command string
		void GetTableSchema(String tableName, out DataTable table, bool full);
		// Does the driver implement non standards commands? If so 
		// it should define a Custom Menu structure
		// but return null if this is not applicable
		CustomMenuItem BuildCustomMenu();
		// supply right-click popups for the given command. Ok to return null
		CustomMenuItem BuildPopupMenu(DbView.Command command);
		// Provide an interface for Import export. Return null if unsupported
		IDatabaseExportSource DatabaseExportSource {get; set; }
		// Provide an interface for Import export. caller should "as" the returned object and
		// allow for null. See existing driver code.
		object TryToGetOptionalInterface(OptionalInterface requestedInterface);
	}

	// For extension without killing drivers.
	// enumerate optional Interfaces. Then ad
	public enum OptionalInterface {Export, Schema, Lookup };

	/*
		 import modes: how to apply staging table data to the target table
		 replace:  delete from target and replace with contents of staging
		 appendOnly: add new rows only - do not update existing rows
		 updateOnly: update existing rows only - do not try to add new rows
		 merge:     insert new rows and update existing rows.
	*/
	public enum CsvImportMode {Replace, AppendOnly, UpdateOnly, Merge };
	//////////////////////////////////////////////////////////////
	// Interface for Import/Export
	// 
	public interface IDatabaseExportSource
	{
		// Connection string property
		String ConnectionString { get; set; }
		// return an array of field info objects representing the 
		// columns or fields of the table for import export
		// properties used: Name, PKey, Auto, Calc (perhaps)
		DbView.FieldInfo[] GetSchema(String tableName);
		// create an empty datatable with the exact schema of the imp/exp table
		// used for mapping csv columns on import.
		DataTable CreateTransferTable(String tableName);
		
		// If staging then create a staging table. This is a separate operation as PopulateTable 
		// may be called multiple times. Set create to false to delete it if it exists.
		void CreateStagingTable(String tableName, bool isStaging, bool create);

		// fill the import table with the data from the csv file loaded into the transfer table
		// bool staging parameter False if applying directly to the table: True for internal staging
		void PopulateTable(String tableName, DataTable data, bool isStaging);

		// If staging update the from the staging table according to the following mode
		// 0 overwrite; 1 update; 2 append new rows only
		void UpdateFromStaging(String tableName, String [] importedFields, CsvImportMode mode);
		
		// return data from the table for the selected fields.
		DataTable ReadData(String tableName, String [] fields, String filterClause, String orderClause);

		// Horrid hack for read loop
		// start a forward read session and return the number of rows
		int ReadInit(String tableName, String [] fields, String filterClause, String orderClause);
		// read the data until exhausted
		bool ReadNext(out object[] data);
		// finish
		void ReadClose();

		// Count the rows in the import table. at present causes the import to halt it non-zero
		int CountRows(String tableName, String filterClause);
	}

	//////////////////////////////////////////////////////////////
	// Interface for use in managing configured connections.
	// At present implemented by the Model class and wrapping the share ConnectionManager class.
	// 
	public interface IConnectionConfig
	{
		// get the current list
		List<DbView.ConnectionInfo> GetConnections();

		// return the current connection - may be null
		DbView.ConnectionInfo GetCurrentConnection();

		// set the current connection
		void SetCurrentConnection(DbView.ConnectionInfo connInfo);
		
		// save changes
		void Save(List<DbView.ConnectionInfo> connectionList);
	}
	
	//////////////////////////////////////////////////////////////
	// Interface for Schema commands
	// 
	// Schema info 
	public interface ISchemaInfo
	{
		// Connection string property
		String ConnectionString { get; }

		// return an array of field info objects representing the 
		// columns or fields of the table for import export
		// properties used: Name, PKey, Auto, Calc (perhaps)
		DbView.FieldInfo[] GetSchema(String tableName);

		// bulk version for when all tables are required
		// however not all fields are guaranteed to be populated. Hm. maybe change this later
		//
		Dictionary<string, DbView.FieldInfo[]> GetBasicSchemas(string[] tableNames);

		// return an array of table names
		string [] GetTables();

		// Populates a datatable with at least the following columns
		// 1. FKTABLE 2. FKFIELD 3. PKTABLE 4. PKFiELD
		// we are leaving aside the issue of multiple foreign keys until later.
		DataTable GetFkInfo();
	}
	//////////////////////////////////////////////////////////////
	// Interface for lookup commands
	// 
	public interface ILookup
	{
		// returns an interface to the schema information.
		ISchemaInfo GetSchemaInfo();

		// Make lookup select f1,f2 from pkTable where keyField in (lookupData)
		// 
		string BuildLookupCommand(string pkTable, string [] pkFields, string keyField, string lookupData);
	}


}